package cn.lingyangwl.agile.tenant.core;

import cn.lingyangwl.agile.model.module.auth.LoginUser;
import cn.lingyangwl.agile.model.module.auth.LoginUserHolder;
import cn.lingyangwl.agile.model.module.tenant.TenantContext;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.Locale;
import java.util.Optional;

/**
 * @author shenguangyang
 */
@ConditionalOnClass(MybatisAutoConfiguration.class)
@Configuration
public class MyBatisPlusTenantConfig {

    @Resource
    private TenantConfig tenantConfig;

    /**
     * 新多租户插件配置
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public String getTenantIdColumn() {
                return "main_tenant_id";
            }

            @Override
            public Expression getTenantId() {
                String mainTenantId = TenantContext.get().getMainTenantId();
                return new LongValue(mainTenantId);
            }

            @Override
            public boolean ignoreTable(String tableName) {
                if (!TenantContext.get().isFilterMainTenant()) {
                    return true;
                }
                return !tenantConfig.getHasMainTenantIdTables().contains(tableName.toLowerCase(Locale.ROOT));
            }
        }));

        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public String getTenantIdColumn() {
                return "tenant_id";
            }

            @Override
            public Expression getTenantId() {
                return new LongValue(TenantContext.get().getTenantId());
            }

            @Override
            public boolean ignoreTable(String tableName) {
                if (!TenantContext.get().isFilterTenant()) {
                    return true;
                }
                return !tenantConfig.getHasTenantIdTables().contains(tableName.toLowerCase(Locale.ROOT));
            }
        }));

        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public String getTenantIdColumn() {
                return "user_id";
            }

            @Override
            public Expression getTenantId() {
                LoginUser loginUser = Optional.ofNullable(LoginUserHolder.get()).orElse(new LoginUser());
                return new LongValue(Optional.ofNullable(loginUser.getUserId()).orElse(-1L));
            }

            @Override
            public boolean ignoreTable(String tableName) {
                return !tenantConfig.getHasUserIdTables().contains(tableName.toLowerCase(Locale.ROOT));
            }
        }));

        // 如果用了分页插件注意先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
        // 向MyBatis-Plus的过滤器链中添加分页拦截器，需要设置数据库类型（主要用于分页方言）
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
